#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
对话框模块 - 包含各种对话框窗口
遵循单一职责原则，专门处理对话框界面

Copyright (c) 2025 RAYA-MAX
Quick-Start is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan
PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from typing import Dict, Any, Optional, Callable
import os

from config_manager import ConfigManager
from launcher import SoftwareLauncher


class ModeManagerWindow:
    """模式管理窗口"""
    
    def __init__(self, parent, config_manager: ConfigManager, refresh_callback: Callable):
        """
        初始化模式管理窗口
        
        Args:
            parent: 父窗口
            config_manager: 配置管理器
            refresh_callback: 刷新回调函数
        """
        self.config_manager = config_manager
        self.refresh_callback = refresh_callback
        
        # 创建窗口
        self.window = tk.Toplevel(parent)
        self.window.title("模式管理")
        self.window.geometry("450x350")
        self.window.resizable(False, False)
        
        # 设置模态窗口
        self.window.transient(parent)
        self.window.grab_set()
        
        self._create_widgets()
        self._refresh_mode_list()
        
        # 居中显示
        self.window.update_idletasks()
        x = (self.window.winfo_screenwidth() // 2) - (self.window.winfo_width() // 2)
        y = (self.window.winfo_screenheight() // 2) - (self.window.winfo_height() // 2)
        self.window.geometry(f"+{x}+{y}")
    
    def _create_widgets(self):
        """创建界面组件"""
        main_frame = ttk.Frame(self.window, padding=20)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 标题
        title_label = ttk.Label(main_frame, text="模式管理", font=("Arial", 14, "bold"))
        title_label.pack(pady=(0, 20))
        
        # 模式列表
        list_frame = ttk.LabelFrame(main_frame, text="现有模式", padding=10)
        list_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 15))

        # 创建列表框
        self.mode_listbox = tk.Listbox(list_frame, height=6)
        self.mode_listbox.pack(fill=tk.BOTH, expand=True)
        
        # 操作按钮
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X, pady=(10, 0))

        # 第一行按钮
        top_button_frame = ttk.Frame(button_frame)
        top_button_frame.pack(fill=tk.X, pady=(0, 5))

        add_btn = ttk.Button(top_button_frame, text="添加模式", command=self._add_mode)
        add_btn.pack(side=tk.LEFT, padx=(0, 10))

        rename_btn = ttk.Button(top_button_frame, text="重命名", command=self._rename_mode)
        rename_btn.pack(side=tk.LEFT, padx=(0, 10))

        delete_btn = ttk.Button(top_button_frame, text="删除模式", command=self._delete_mode)
        delete_btn.pack(side=tk.LEFT)

        # 第二行按钮
        bottom_button_frame = ttk.Frame(button_frame)
        bottom_button_frame.pack(fill=tk.X)

        close_btn = ttk.Button(bottom_button_frame, text="关闭", command=self._close_window)
        close_btn.pack(side=tk.RIGHT)
    
    def _refresh_mode_list(self):
        """刷新模式列表"""
        self.mode_listbox.delete(0, tk.END)
        modes = self.config_manager.get_modes()
        for mode in modes:
            self.mode_listbox.insert(tk.END, mode)
    
    def _add_mode(self):
        """添加新模式"""
        dialog = SimpleInputDialog(self.window, "添加模式", "请输入新模式名称:")
        if dialog.result:
            mode_name = dialog.result.strip()
            if mode_name:
                if self.config_manager.add_mode(mode_name):
                    self._refresh_mode_list()
                    messagebox.showinfo("成功", f"模式 '{mode_name}' 添加成功")
                else:
                    messagebox.showerror("错误", "模式名称已存在或无效")
            else:
                messagebox.showwarning("警告", "模式名称不能为空")
    
    def _rename_mode(self):
        """重命名模式"""
        selection = self.mode_listbox.curselection()
        if not selection:
            messagebox.showwarning("提示", "请先选择要重命名的模式")
            return
        
        old_name = self.mode_listbox.get(selection[0])
        dialog = SimpleInputDialog(self.window, "重命名模式", f"请输入新名称:", old_name)
        
        if dialog.result:
            new_name = dialog.result.strip()
            if new_name and new_name != old_name:
                if self.config_manager.rename_mode(old_name, new_name):
                    self._refresh_mode_list()
                    messagebox.showinfo("成功", f"模式已重命名为 '{new_name}'")
                else:
                    messagebox.showerror("错误", "新名称已存在或无效")
            elif new_name == old_name:
                messagebox.showinfo("提示", "名称未改变")
            else:
                messagebox.showwarning("警告", "模式名称不能为空")
    
    def _delete_mode(self):
        """删除模式"""
        selection = self.mode_listbox.curselection()
        if not selection:
            messagebox.showwarning("提示", "请先选择要删除的模式")
            return
        
        mode_name = self.mode_listbox.get(selection[0])
        
        if messagebox.askyesno("确认删除", f"确定要删除模式 '{mode_name}' 吗？\n删除后该模式下的所有软件配置也会丢失。"):
            if self.config_manager.delete_mode(mode_name):
                self._refresh_mode_list()
                messagebox.showinfo("成功", f"模式 '{mode_name}' 已删除")
            else:
                messagebox.showerror("错误", "无法删除模式（可能是最后一个模式）")
    
    def _close_window(self):
        """关闭窗口"""
        self.refresh_callback()  # 刷新主窗口
        self.window.destroy()


class SoftwareEditWindow:
    """软件编辑窗口"""
    
    def __init__(self, parent, config_manager: ConfigManager, mode_name: str, 
                 software_info: Optional[Dict[str, str]] = None, 
                 software_index: Optional[int] = None,
                 refresh_callback: Optional[Callable] = None):
        """
        初始化软件编辑窗口
        
        Args:
            parent: 父窗口
            config_manager: 配置管理器
            mode_name: 模式名称
            software_info: 软件信息（编辑时使用）
            software_index: 软件索引（编辑时使用）
            refresh_callback: 刷新回调函数
        """
        self.config_manager = config_manager
        self.mode_name = mode_name
        self.software_info = software_info or {}
        self.software_index = software_index
        self.refresh_callback = refresh_callback
        self.is_edit_mode = software_info is not None
        
        # 创建窗口
        self.window = tk.Toplevel(parent)
        self.window.title("编辑软件" if self.is_edit_mode else "添加软件")
        self.window.geometry("500x300")
        self.window.resizable(False, False)
        
        # 设置模态窗口
        self.window.transient(parent)
        self.window.grab_set()
        
        self._create_widgets()
        
        # 居中显示
        self.window.update_idletasks()
        x = (self.window.winfo_screenwidth() // 2) - (self.window.winfo_width() // 2)
        y = (self.window.winfo_screenheight() // 2) - (self.window.winfo_height() // 2)
        self.window.geometry(f"+{x}+{y}")
    
    def _create_widgets(self):
        """创建界面组件"""
        main_frame = ttk.Frame(self.window, padding=20)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 标题
        title = "编辑软件" if self.is_edit_mode else "添加软件"
        title_label = ttk.Label(main_frame, text=title, font=("Arial", 14, "bold"))
        title_label.pack(pady=(0, 20))
        
        # 表单区域
        form_frame = ttk.Frame(main_frame)
        form_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 20))
        
        # 软件名称
        ttk.Label(form_frame, text="软件名称:").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.name_var = tk.StringVar(value=self.software_info.get('name', ''))
        name_entry = ttk.Entry(form_frame, textvariable=self.name_var, width=40)
        name_entry.grid(row=0, column=1, columnspan=2, sticky=tk.W+tk.E, pady=5, padx=(10, 0))
        
        # 软件路径
        ttk.Label(form_frame, text="软件路径:").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.path_var = tk.StringVar(value=self.software_info.get('path', ''))
        path_entry = ttk.Entry(form_frame, textvariable=self.path_var, width=30)
        path_entry.grid(row=1, column=1, sticky=tk.W+tk.E, pady=5, padx=(10, 5))
        
        browse_btn = ttk.Button(form_frame, text="浏览", command=self._browse_file)
        browse_btn.grid(row=1, column=2, pady=5)
        
        # 软件描述
        ttk.Label(form_frame, text="软件描述:").grid(row=2, column=0, sticky=tk.W+tk.N, pady=5)
        self.desc_var = tk.StringVar(value=self.software_info.get('description', ''))
        desc_entry = tk.Text(form_frame, width=40, height=4)
        desc_entry.grid(row=2, column=1, columnspan=2, sticky=tk.W+tk.E, pady=5, padx=(10, 0))
        desc_entry.insert('1.0', self.software_info.get('description', ''))
        self.desc_text = desc_entry
        
        # 配置网格权重
        form_frame.columnconfigure(1, weight=1)
        
        # 按钮区域 - 居中布局
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X)

        # 创建内部框架用于居中按钮
        center_frame = ttk.Frame(button_frame)
        center_frame.pack(anchor=tk.CENTER)

        save_btn = ttk.Button(center_frame, text="保存", command=self._save_software)
        save_btn.pack(side=tk.LEFT, padx=(0, 10))

        cancel_btn = ttk.Button(center_frame, text="取消", command=self.window.destroy)
        cancel_btn.pack(side=tk.LEFT)
        
        # 如果是编辑模式，添加测试按钮
        if self.is_edit_mode:
            test_btn = ttk.Button(button_frame, text="测试启动", command=self._test_launch)
            test_btn.pack(side=tk.RIGHT)
    
    def _browse_file(self):
        """浏览文件"""
        file_path = filedialog.askopenfilename(
            title="选择软件文件",
            filetypes=[
                ("可执行文件", "*.exe"),
                ("批处理文件", "*.bat"),
                ("所有文件", "*.*")
            ]
        )
        if file_path:
            self.path_var.set(file_path)
            # 如果名称为空，自动填入文件名
            if not self.name_var.get():
                filename = os.path.splitext(os.path.basename(file_path))[0]
                self.name_var.set(filename)
    
    def _save_software(self):
        """保存软件信息"""
        name = self.name_var.get().strip()
        path = self.path_var.get().strip()
        description = self.desc_text.get('1.0', tk.END).strip()
        
        if not name:
            messagebox.showwarning("警告", "请输入软件名称")
            return
        
        if not path:
            messagebox.showwarning("警告", "请选择软件路径")
            return
        
        # 验证路径
        launcher = SoftwareLauncher()
        is_valid, message = launcher.validate_software_path(path)
        if not is_valid:
            if not messagebox.askyesno("路径警告", f"软件路径验证失败: {message}\n是否仍要保存？"):
                return
        
        software_info = {
            'name': name,
            'path': path,
            'description': description
        }
        
        success = False
        if self.is_edit_mode and self.software_index is not None:
            # 编辑模式
            success = self.config_manager.update_software(
                self.mode_name, self.software_index, software_info
            )
        else:
            # 添加模式
            success = self.config_manager.add_software(self.mode_name, software_info)
        
        if success:
            messagebox.showinfo("成功", "软件信息保存成功")
            if self.refresh_callback:
                self.refresh_callback()
            self.window.destroy()
        else:
            messagebox.showerror("错误", "保存失败")
    
    def _test_launch(self):
        """测试启动软件"""
        path = self.path_var.get().strip()
        name = self.name_var.get().strip() or "测试软件"
        
        if not path:
            messagebox.showwarning("警告", "请先选择软件路径")
            return
        
        launcher = SoftwareLauncher()
        success, message = launcher.launch_software(path, name)
        
        if success:
            messagebox.showinfo("测试成功", f"软件 '{name}' 启动成功")
        else:
            messagebox.showerror("测试失败", f"启动失败: {message}")


class SimpleInputDialog:
    """简单输入对话框"""
    
    def __init__(self, parent, title: str, prompt: str, initial_value: str = ""):
        """
        初始化输入对话框
        
        Args:
            parent: 父窗口
            title: 对话框标题
            prompt: 提示文本
            initial_value: 初始值
        """
        self.result = None
        
        # 创建窗口
        self.window = tk.Toplevel(parent)
        self.window.title(title)
        self.window.geometry("300x150")
        self.window.resizable(False, False)
        
        # 设置模态窗口
        self.window.transient(parent)
        self.window.grab_set()
        
        # 创建界面
        main_frame = ttk.Frame(self.window, padding=20)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 提示标签
        ttk.Label(main_frame, text=prompt).pack(pady=(0, 10))
        
        # 输入框
        self.entry_var = tk.StringVar(value=initial_value)
        entry = ttk.Entry(main_frame, textvariable=self.entry_var, width=30)
        entry.pack(pady=(0, 20))
        entry.focus()
        entry.select_range(0, tk.END)
        
        # 按钮
        button_frame = ttk.Frame(main_frame)
        button_frame.pack()
        
        ok_btn = ttk.Button(button_frame, text="确定", command=self._ok_clicked)
        ok_btn.pack(side=tk.LEFT, padx=(0, 10))
        
        cancel_btn = ttk.Button(button_frame, text="取消", command=self._cancel_clicked)
        cancel_btn.pack(side=tk.LEFT)
        
        # 绑定回车键
        self.window.bind('<Return>', lambda e: self._ok_clicked())
        self.window.bind('<Escape>', lambda e: self._cancel_clicked())
        
        # 居中显示
        self.window.update_idletasks()
        x = (self.window.winfo_screenwidth() // 2) - (self.window.winfo_width() // 2)
        y = (self.window.winfo_screenheight() // 2) - (self.window.winfo_height() // 2)
        self.window.geometry(f"+{x}+{y}")
        
        # 等待用户操作
        self.window.wait_window()
    
    def _ok_clicked(self):
        """确定按钮点击"""
        self.result = self.entry_var.get()
        self.window.destroy()
    
    def _cancel_clicked(self):
        """取消按钮点击"""
        self.result = None
        self.window.destroy()
